package org.apereo.cas.web;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.validator.routines.DomainValidator;
import org.apache.commons.validator.routines.RegexValidator;
import org.springframework.beans.factory.FactoryBean;


/**
 * The factory to build a {@link UrlValidator}.
 *
 * @author swoeste
 * @since 5.2.0
 */
@Slf4j
public class SimpleUrlValidatorFactoryBean implements FactoryBean<UrlValidator> {

    private static final org.apache.commons.validator.routines.UrlValidator URL_VALIDATOR_ALLOW_LOCAL_URLS = new org.apache.commons.validator.routines.UrlValidator(org.apache.commons.validator.routines.UrlValidator.ALLOW_LOCAL_URLS);

    private final boolean allowLocalUrls;
    private final org.apache.commons.validator.routines.UrlValidator urlValidatorWithRegex;

    public SimpleUrlValidatorFactoryBean(final boolean allowLocalUrls) {
        this(allowLocalUrls, null, true);
    }

    public SimpleUrlValidatorFactoryBean(final boolean allowLocalUrls, final String authorityValidationRegEx,
        final boolean authorityValidationRegExCaseSensitive) {
        this.allowLocalUrls = allowLocalUrls;
        this.urlValidatorWithRegex = createUrlValidatorWithRegex(allowLocalUrls, authorityValidationRegEx, authorityValidationRegExCaseSensitive);
    }

    private org.apache.commons.validator.routines.UrlValidator createUrlValidatorWithRegex(final boolean allowLocalUrls, final String authorityValidationRegEx,
        final boolean authorityValidationRegExCaseSensitive) {
        if (StringUtils.isEmpty(authorityValidationRegEx)) {
            return null;
        }

        final RegexValidator authorityValidator = new RegexValidator(authorityValidationRegEx, authorityValidationRegExCaseSensitive);
        final long options = allowLocalUrls ? org.apache.commons.validator.routines.UrlValidator.ALLOW_LOCAL_URLS : 0;
        return new org.apache.commons.validator.routines.UrlValidator(authorityValidator, options);
    }

    @Override
    public UrlValidator getObject() {
        return new SimpleUrlValidator(getUrlValidator(), getDomainValidator());
    }

    private org.apache.commons.validator.routines.UrlValidator getUrlValidator() {
        if (this.urlValidatorWithRegex != null) {
            return urlValidatorWithRegex;
        }

        if (this.allowLocalUrls) {
            return URL_VALIDATOR_ALLOW_LOCAL_URLS;
        }

        return org.apache.commons.validator.routines.UrlValidator.getInstance();
    }

    public DomainValidator getDomainValidator() {
        return DomainValidator.getInstance(this.allowLocalUrls);
    }

    @Override
    public Class<?> getObjectType() {
        return SimpleUrlValidator.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

}
